package com.shujia.day18;

/*
    使用实现Runnable接口的方式实现售票

    问题1：我们加入了循环和延迟模拟现实生活售票的场景后发现
        1. 出现售卖重复的票号 【计算机中cpu的计算是具备原子性的】
        2. 出现非法的票号  【随机性导致的，cpu小小的时间片，足以执行很多次】

    上述的问题1实际上是属于线程安全的问题。
    如何判断一个程序是否存在线程安全的问题呢？
    三要素，缺一不可：
        1、是否存在多线程环境？ 是
        2、是否存在共享数据/共享变量？是tickets
        3、是否存在多条语句操作着共享数据/共享变量？ 是

    怎么解决？
        方案1：同步代码块
            synchronized(对象){需要同步的代码;}  这里对象要保证多个线程对象唯一的
            同步方法：锁对象是this
            同步静态方法：锁对象是当前类的class文件对象   类.class
        方案2：lock锁



 */
class Window2 implements Runnable{
    int tickets = 200;
    Object obj = new Object();

    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if(tickets>0){ // 1
                    try {
                        // t1
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("当前 " + Thread.currentThread().getName()+" 正在出售第 "+(tickets--)+" 张票");
                }
            }

        }
    }
}


public class SellTicketsDemo2 {
    public static void main(String[] args) {
        Window2 window2 = new Window2();

        Thread t1 = new Thread(window2, "窗口1");
        Thread t2 = new Thread(window2, "窗口2");
        Thread t3 = new Thread(window2, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}
